package com.topnav.mc.schedule.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.topnav.mc.admin.entity.DeviceLog;
import com.topnav.mc.admin.entity.DeviceOnlineTotal;
import com.topnav.mc.admin.service.IDeviceLogService;
import com.topnav.mc.admin.service.IDeviceOnlineTotalService;
import com.topnav.mc.lock.SyncLock;
import com.topnav.mc.uitls.DeviceOnlineUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 定时计算设备在线时间
 * @Author: kenny
 * @Date: 2023/10/31 15:39
 */
@Component
@Slf4j
public class CalculateDeviceOnlineTimeJob implements Job, Serializable {
    @Autowired
    private IDeviceOnlineTotalService deviceOnlineTotalService;
    @Autowired
    private IDeviceLogService deviceLogService;
    @Autowired
    private DeviceOnlineUtils deviceOnlineUtils;

    @Override
    @SyncLock(key = "CalculateDeviceOnlineTimeJob.execute-LOCK", dueSec = 1 * 60 * 60)
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try{
            this.execute1();
        }catch (Exception e){
            log.error(">>>>>>>>> 计算设备在线时间异常: {}",e.toString());
        }
    }

    private void execute1(){
        // 查询上次一直连续在线的设备数据
        LambdaQueryWrapper<DeviceOnlineTotal> wrapper = new LambdaQueryWrapper();
        wrapper.eq(DeviceOnlineTotal::getClose,false);
        List<DeviceOnlineTotal> deviceOnlineTotalList = deviceOnlineTotalService.list(wrapper);

        //查询未计算上下线时间的设备日志记录
        LambdaQueryWrapper<DeviceLog> wrapper1 = new LambdaQueryWrapper();
        wrapper1.eq(DeviceLog::getSynch,false);
        wrapper1.orderByAsc(DeviceLog::getDeviceId,DeviceLog::getCreateTime);
        List<DeviceLog> deviceLogList = deviceLogService.list(wrapper1);

        //处理
        Long backDeviceId=null;
        boolean first = false;
        int backAtion = 0;
        DeviceLog backDeviceLog=null;
        DeviceOnlineTotal deviceOnlineTotal = null;
        //UpdateWrapper<DeviceLog> updateWrapper = new UpdateWrapper<>();
        for(DeviceLog deviceLog : deviceLogList){
            first = false;
            if (backDeviceId == null){
                backDeviceId = deviceLog.getDeviceId();
                first = true;
            }
            if (!backDeviceId.equals(deviceLog.getDeviceId())){
                if (deviceOnlineTotal != null){
                    //如果上一个没保存，说明是连续在线的设备
                    this.saveDot(deviceOnlineTotal);
                    deviceOnlineTotal = null;
                }
                //换一个新的设备了
                backDeviceId = deviceLog.getDeviceId();
                first = true;
            }

            //第一个就下线，要更新下一次上线的为下线并计算在线时间
            if (deviceLog.getAction() == 0){
                if (first){
                    //第一笔记录就是下线，那么可能是连续在线的设备
                    //找到DeviceOnlineTotal 最近一笔上线时间，并计算在时间 更新回表DeviceOnlineTotal中
                    for(DeviceOnlineTotal deviceOnlineTotal1 : deviceOnlineTotalList){
                        if (deviceOnlineTotal1.getDeviceId() == deviceLog.getDeviceId()){
                            //关闭些在上下线事件
                            deviceOnlineTotal1.setClose(true);
                            deviceOnlineTotal1.setOnlineSec(
                                    (
                                            (deviceLog.getCreateTime()).getTime() - deviceOnlineTotal1.getStartTime().getTime()
                                    )/1000
                            );
                            deviceOnlineTotal1.setEndTime(deviceLog.getCreateTime());
                            deviceOnlineTotalService.updateById(deviceOnlineTotal1);
                            break;
                        }
                    }
                }
                else{
                    if (backAtion==0){
                        //连续的0 什么也不做，继续
                        this.closeDeviceLog(deviceLog);
                        continue;
                    }
                    if (deviceOnlineTotal != null){
                        deviceOnlineTotal.setClose(true);
                        deviceOnlineTotal.setEndTime(deviceLog.getCreateTime());
                        deviceOnlineTotal.setOnlineSec(
                                (
                                        (deviceLog.getCreateTime()).getTime() - deviceOnlineTotal.getStartTime().getTime()
                                )/1000
                        );
                        deviceOnlineTotalService.save(deviceOnlineTotal);
                        //更新到数据，并结束本轮
                        deviceOnlineTotal = null;
                    }
                }
            }else if (deviceLog.getAction() == 1){
                if (first){
                    //找到上一次并更新为结束,且加一条新的记录
                    for(DeviceOnlineTotal deviceOnlineTotal1 : deviceOnlineTotalList){
                        if (deviceOnlineTotal1.getDeviceId() == deviceLog.getDeviceId()){
                            //关闭些在上下线事件
                            deviceOnlineTotal1.setClose(true);
                            deviceOnlineTotal1.setOnlineSec(
                                    (
                                            (deviceLog.getCreateTime()).getTime() - deviceOnlineTotal1.getStartTime().getTime()
                                    )/1000
                            );
                            deviceOnlineTotal1.setEndTime(deviceLog.getCreateTime());
                            deviceOnlineTotalService.updateById(deviceOnlineTotal1);
                            break;
                        }
                    }
                    //加一条新的
                    deviceOnlineTotal = this.newDot(deviceLog);
                }else{
                    if (backAtion==1){
                        //连续的1 什么也不做，继续
                        this.closeDeviceLog(deviceLog);
                        continue;
                    }
                    //加一条新的数据
                    deviceOnlineTotal = this.newDot(deviceLog);
                }
            }


            this.closeDeviceLog(deviceLog);
            backAtion = deviceLog.getAction();
        }

        //剩下的是连续在线设备，继续保存
        if (deviceOnlineTotal != null){
            saveDot(deviceOnlineTotal);
        }

        for(DeviceOnlineTotal deviceOnlineTotal1 : deviceOnlineTotalList){
            //本轮没有发生上下线事件的重新计算在线时长继续保存
            if (!deviceOnlineTotal1.getClose()){
                if (deviceOnlineUtils.isOnline(deviceOnlineTotal1.getDeviceCode())){
                    //在线加一小时
                    deviceOnlineTotal1.setEndTime(new Date((new Date().getTime() + 5*60*1000)));
                }else{
                    //离线关闭
                    deviceOnlineTotal1.setClose(true);
                    deviceOnlineTotal1.setEndTime(new Date());
                }
                deviceOnlineTotal1.setOnlineSec(
                        (
                                (new Date()).getTime() - deviceOnlineTotal1.getStartTime().getTime()
                        )/1000
                );

                deviceOnlineTotalService.updateById(deviceOnlineTotal1);
            }
        }
    }

    /**
     * 本次没下线的延续到以后
     * @param deviceOnlineTotal
     */
    private void saveDot(DeviceOnlineTotal deviceOnlineTotal){
        if (deviceOnlineUtils.isOnline(deviceOnlineTotal.getDeviceCode())){
            //在线加一小时
            deviceOnlineTotal.setEndTime(new Date((new Date().getTime() + 1*60*60*1000)));
        }else{
            //离线关闭
            deviceOnlineTotal.setClose(true);
            deviceOnlineTotal.setEndTime(new Date());
        }
        deviceOnlineTotal.setOnlineSec(
                (
                        (new Date()).getTime() - deviceOnlineTotal.getStartTime().getTime()
                )/1000
        );
        if (deviceOnlineTotal.getId() == null){
            deviceOnlineTotalService.save(deviceOnlineTotal);
        }else{
            deviceOnlineTotalService.updateById(deviceOnlineTotal);
        }
        //deviceOnlineTotalService.updateById(deviceOnlineTotal);
    }

    /**
     * 生成新的 DeviceOnlineTotal
     * @param deviceLog
     * @return
     */
    private DeviceOnlineTotal newDot(DeviceLog deviceLog){
        DeviceOnlineTotal deviceOnlineTotal = new DeviceOnlineTotal();
        deviceOnlineTotal.setDeviceId(deviceLog.getDeviceId());
        deviceOnlineTotal.setStartTime(deviceLog.getCreateTime());
        deviceOnlineTotal.setClose(false);
        deviceOnlineTotal.setDeviceCode(deviceLog.getDeviceCode());
        deviceOnlineTotal.setCreateTime(new Date());
        deviceOnlineTotal.setUpdateTime(new Date());
        return deviceOnlineTotal;
    }

    /**
     * 生成新DeviceLog 为已同步
     * @param deviceLog
     * @return
     */
    private void  closeDeviceLog(DeviceLog deviceLog){
        //更新回DeviceLog
        UpdateWrapper<DeviceLog> updateWrapper = new UpdateWrapper<>();
        updateWrapper.clear();
        updateWrapper.set("synch",true).eq("id",deviceLog.getId());
        deviceLogService.update(updateWrapper);
    }
}
